#include <aos/kernel.h>
#include <aos/errno.h>
#include <string.h>
#include "faceproc.h"
#include "rectify_param.h"
#include "ipcm.h"

#ifndef CHECK_PARAM
#define CHECK_PARAM(x, ret) \
	do { \
		if (!(x)) { \
			return ret; \
		}\
	} while (0)
#endif

#ifndef CHECK_RET
#define CHECK_RET(x, ret) \
	do { \
		if (x) { \
			return ret; \
		}\
	} while (0)
#endif

/* Message Command (16bit)*/
#define IPCM_GET_VERSION          0x0001
#define IPCM_SET_LOG_LEVEL        0x0002
#define IPCM_GET_MODEL_VERSION    0x0003
#define IPC_AIE_PROC_INIT         0x0101
#define IPC_AIE_SET_PARAM         0x0102
#define IPC_AIE_GET_PARAM         0x0103
#define IPC_AIE_PROC_RUN          0x0104
#define IPC_AIE_PROC_REG          0x0105
#define IPC_AIE_PROC_MATCH        0x0106
#define IPC_AIE_PROC_RESIZE       0x0107
#define IPC_AIE_PROC_ROTATE90     0x0108

/* single eye processing */
#define IPC_AIE_PROC_INIT_SINGLE  		        0x0201
#define IPC_AIE_PROC_RUN_SINGLE   		        0x0202
#define IPC_AIE_PROC_RUN_SINGLE_DISP   	        0x0203
#define IPC_AIE_PROC_RUN_SINGLE_2BASE_DEPTH   	0x0204
#define IPC_AIE_PROC_INIT_DOUBLE_IR   		    0x0203
#define IPC_AIE_PROC_RUN_DOUBLE_IR   		    0x0204

#define IPC_AIE_INIT_DEPTH_COMPEN_SINGLE_EYE    0x0205
#define IPC_AIE_PROC_DEPTH_COMPEN_SINGLE_EYE    0x0206

#define IPC_AIE_GET_FACE_LUMA           0x0301
#define IPC_AIE_GET_FACE_LUMA_ROI       0x0302

#define IPC_AIE_SL3D_STREAM_INIT        0x0303
#define IPC_AIE_SL3D_STREAM_IN          0x0304
#define IPC_AIE_SL3D_STREAM_OUT         0x0305

#define  IPC_TOF_GET_IR_DEPTH           0x401

#define  IPC_HUMANPOSE_INIT      		0x501
#define  IPC_HUMANPOSE_DETECT    		0x502
#define  IPC_IMAGE_BINA                 0x601

#define IPCM_ALGO_GET_RECTIFY_PARAM      0x0701


typedef struct
{
	int h;
	int w;
	int face_vec_num;
	int16_t 		* face_vec;
	tsmHW3DParam	hw3d_param;
	void  			* hw3d_param_ram;
} tsmInitParam;

typedef struct
{
	void *vis;
	void *nir;
	void *left;
	void *right;
    void *depth;
    tsmRunMode_t run_mode;
} tsmFaceProcessInput;

typedef struct
{
	void *		ir;
	TsmFaceBox	roi;
}tsmLumaRoi;

typedef struct
{
    grey_img_t *in;
    grey_img_t *out;
}tsmTRP_Bina_t;


int TSM_ALGO_FaceProcInit(TsmHandle handle, int h, int w,
                    int face_vec_num, int16_t *face_vec , 
                    void * hw3d_param)
{
    void *ipcm = ipcm_get(IPCM_CPU_ID_CK805);
    CHECK_PARAM(ipcm, -EBUSY);
    tsmInitParam* p_init_param = (tsmInitParam *)ipcm_get_mem();
    CHECK_PARAM(p_init_param, -ENOMEM);
    p_init_param->h            = h;
    p_init_param->w            = w;
    p_init_param->face_vec_num = face_vec_num;
    p_init_param->face_vec     = face_vec;
    memcpy(&(p_init_param->hw3d_param), hw3d_param, sizeof(tsmHW3DParam));
    
    int* rev ;
    int  ret = 0;
    ret = ipcm_sync_send(ipcm, IPC_AIE_PROC_INIT, (void*)p_init_param, &rev);
    
    if (ret != 0) { 
        return ret;
    }
    
    return (int)*rev;
}

int TSM_ALGO_SetFaceProcessParam(TsmHandle handle, tsmFaceProcessParam * param)
{
	void *ipcm = ipcm_get(IPCM_CPU_ID_CK805);
    CHECK_PARAM(ipcm, -EBUSY);
    tsmFaceProcessParam * p_set_param = (tsmFaceProcessParam *)ipcm_get_mem();
    CHECK_PARAM(p_set_param, -ENOMEM);
    memcpy(p_set_param, param, sizeof(tsmFaceProcessParam));
    int* rev;
    int  ret = 0;
    ret = ipcm_sync_send(ipcm, IPC_AIE_SET_PARAM, (void*)p_set_param, &rev);
    if (ret != 0) {    
        return ret;
    }
    
    return 0;
}


int TSM_ALGO_GetFaceProcessParam(TsmHandle handle, tsmFaceProcessParam * param)
{
	void *ipcm = ipcm_get(IPCM_CPU_ID_CK805);
    CHECK_PARAM(ipcm, -EBUSY);
    tsmFaceProcessParam* p_get_param = (tsmFaceProcessParam *)ipcm_get_mem();
    // int param_dummy = 0;
    int  ret = 0;
	int* rev;
    ret = ipcm_sync_send(ipcm, IPC_AIE_GET_PARAM, (void*)p_get_param, &rev);
    if (ret != 0) {    
        return ret;
    }
	memcpy(param, p_get_param, sizeof(tsmFaceProcessParam));
	
    return 0;
}


algo_rectify_output_t *TSM_ALGO_CalibOnLineRun(TsmHandle handle, int h, int w, float baseline, float focus, void *img_l, RectifyPoint *l,
                              void *img_r, RectifyPoint *r)
{
	void *ipcm = ipcm_get(IPCM_CPU_ID_CK805);
    CHECK_PARAM(ipcm, NULL);
	tsmTRP_Rectify_t * p_proc_run = (tsmTRP_Rectify_t *)ipcm_get_mem();
    CHECK_PARAM(p_proc_run, NULL);
    p_proc_run->mode = RECTIFY_PARAM_SINGLE;
    p_proc_run->width = w;
    p_proc_run->height = h;
    p_proc_run->distanceBetweenCameras = baseline;
    p_proc_run->foucs = focus;
    p_proc_run->left_image = img_l;
    p_proc_run->left_point = l;
    p_proc_run->right_image = img_r;
    p_proc_run->right_point = r;
    p_proc_run->point_num = 25;

    int* rev;
    int  ret = 0;
    /* TODO:what about error code? */
    ret = ipcm_sync_send(ipcm, IPCM_ALGO_GET_RECTIFY_PARAM, (void*)p_proc_run, &rev);
    if (ret != 0) {    
        return NULL;
    }
    algo_rectify_output_t* result = (algo_rectify_output_t*)rev;
    return result;
}

TsmFaceResult *TSM_ALGO_FaceProcRun(TsmHandle handle, uint32_t *img_0rgb,
                              TsmSl3dInput *img_3de, void *img_nir,
                              tsmRunMode_t * run_mode)
{
	void *ipcm = ipcm_get(IPCM_CPU_ID_CK805);
    CHECK_PARAM(ipcm, NULL);
    tsmFaceProcessInput * p_proc_run = (tsmFaceProcessInput *)ipcm_get_mem();
    CHECK_PARAM(p_proc_run, NULL);
    
    p_proc_run->vis   = img_0rgb;
    p_proc_run->left  = img_3de->img_l;
    p_proc_run->right = img_3de->img_r;
    p_proc_run->depth = img_3de->depth_input;
    p_proc_run->nir   = img_nir;
    if(NULL != run_mode) {
        memcpy(&(p_proc_run->run_mode), run_mode, sizeof(tsmRunMode_t));
    } else {
        memset(&(p_proc_run->run_mode), 0, sizeof(tsmRunMode_t));
    }
    
    int* rev;
    int  ret = 0;
    /* TODO:what about error code? */
    ret = ipcm_sync_send(ipcm, IPC_AIE_PROC_RUN, (void*)p_proc_run, &rev);
    if (ret != 0) {    
        return NULL;
    }
    TsmFaceResult* result = (TsmFaceResult*)rev;
    return result;
}

TsmFaceResult *TSM_ALGO_FaceProcReg(TsmHandle handle, uint32_t *img_0rgb,
                              TsmSl3dInput *img_3de, void *img_nir,
                              tsmRunMode_t * run_mode)
{
	void *ipcm = ipcm_get(IPCM_CPU_ID_CK805);
    CHECK_PARAM(ipcm, NULL);
    tsmFaceProcessInput * p_proc_run = (tsmFaceProcessInput *)ipcm_get_mem();
    CHECK_PARAM(p_proc_run, NULL);
    /* TODO: check user`s param ? */
    p_proc_run->vis   = img_0rgb;
    p_proc_run->left  = img_3de->img_l;
    p_proc_run->right = img_3de->img_r;
    p_proc_run->depth = img_3de->depth_input;
    p_proc_run->nir   = img_nir;
    memcpy(&(p_proc_run->run_mode), run_mode, sizeof(tsmRunMode_t));
    int* rev;
    int  ret = 0;
    ret = ipcm_sync_send(ipcm, IPC_AIE_PROC_REG, (void*)p_proc_run, &rev);
    if (ret != 0) {    
        return NULL;
    }
    TsmFaceResult* result = (TsmFaceResult*)rev;
    return result;
}
int TSM_ALGO_GetFaceLuma(TsmHandle handle, void *img_nir)
{
	void *ipcm = ipcm_get(IPCM_CPU_ID_CK805);
    CHECK_PARAM(ipcm, -EBUSY);
    CHECK_PARAM(img_nir, -1);
    int* rev;
    int  ret = 0;
    ret = ipcm_sync_send(ipcm, IPC_AIE_GET_FACE_LUMA, (void*)img_nir, &rev);
    if (ret != 0) {    
        return -1;
    }
    int result = *(int*)rev;
    return result;
}

int TSM_ALGO_GetFaceLumaRoi(TsmHandle handle, void *img_nir, TsmFaceBox* box)
{
	void *ipcm = ipcm_get(IPCM_CPU_ID_CK805);
    CHECK_PARAM(ipcm, -EBUSY);
    CHECK_PARAM(img_nir, 0);
    CHECK_PARAM(box, 0);
    int* rev;
    int  ret = 0;
    tsmLumaRoi * p_luam_roi = (tsmLumaRoi *)ipcm_get_mem();
    p_luam_roi->ir = img_nir;
    memcpy(&(p_luam_roi->roi), box, sizeof(TsmFaceBox));
    ret = ipcm_sync_send(ipcm, IPC_AIE_GET_FACE_LUMA_ROI, (void*)p_luam_roi, &rev);
    if (ret != 0) {    
        return 0;
    }
    int result = *(int*)rev;
    return result;
}

TsmMatchResult * TSM_ALGO_RunAmrMatch(tsmMatchParam *match_param)
{
	void *ipcm = ipcm_get(IPCM_CPU_ID_CK805);
    CHECK_PARAM(ipcm, NULL);
    tsmMatchParam* p_match = (tsmMatchParam*)ipcm_get_mem();
    CHECK_PARAM(p_match, NULL);
    memcpy(p_match, match_param, sizeof(tsmMatchParam));
    int* rev;
    int  ret = 0;
    ret = ipcm_sync_send(ipcm, IPC_AIE_PROC_MATCH, (void*)p_match, &rev);
    if (ret != 0) {    
        return NULL;
    }
    TsmMatchResult* result = (TsmMatchResult*)rev;
    return result;
}
#if 1
int TSM_ALGO_RunAmrResize(tsmImg_t* src, tsmImg_t* dst)
{
	void *ipcm = ipcm_get(IPCM_CPU_ID_CK805);
    CHECK_PARAM(ipcm, -EBUSY);
    static int amr_init = 0;
    if (amr_init == 0) {
        ipcm = ipcm_get(IPCM_CPU_ID_CK805);
        amr_init++;
    }
    tsmResizeData_t* p_match = (tsmResizeData_t*)ipcm_get_mem();
    CHECK_PARAM(src, -1);
    CHECK_PARAM(dst, -1);
    memcpy(&(p_match->src), src, sizeof(tsmImg_t));
    memcpy(&(p_match->dst), dst, sizeof(tsmImg_t));
    int* rev;
    int  ret = 0;
    ret = ipcm_sync_send(ipcm, IPC_AIE_PROC_RESIZE, (void*)p_match, &rev);
    if (ret != 0) {    
        return -1;
    }
    int result = *(int*)rev;
    return result;
}
#endif 

int TSM_ALGO_InitSl3dDepth_SingleEye(tsmTRP_Sl3dCfg_t* data)
{
	void *ipcm = ipcm_get(IPCM_CPU_ID_CK805);
    CHECK_PARAM(ipcm, -EBUSY);
    tsmTRP_Sl3dCfg_t* p_sl3d = (tsmTRP_Sl3dCfg_t*)ipcm_get_mem();
    CHECK_PARAM(p_sl3d, -1);
    memcpy(p_sl3d, data, sizeof(tsmTRP_Sl3dCfg_t));
    int* rev;
    int  ret = 0;
    ret = ipcm_sync_send(ipcm, IPC_AIE_PROC_INIT_SINGLE, (void*)p_sl3d, &rev);
    if (ret != 0) {    
        return ret;
    }
    return 0;
}

int TSM_ALGO_InitSl3dDepth_doubleIR(tsmTRP_Sl3dCfg_t* data)
{
    void *ipcm = ipcm_get(IPCM_CPU_ID_CK805);
    CHECK_PARAM(ipcm, -EBUSY);
    tsmTRP_Sl3dCfg_t* p_sl3d = (tsmTRP_Sl3dCfg_t*)ipcm_get_mem();
    CHECK_PARAM(p_sl3d, -1);
    memcpy(p_sl3d, data, sizeof(tsmTRP_Sl3dCfg_t));
    int* rev;
    int  ret = 0;
    ret = ipcm_sync_send(ipcm, IPC_AIE_PROC_INIT_DOUBLE_IR, (void*)p_sl3d, &rev);
    if (ret != 0) {    
        return ret;
    }

    return 0;
}

int TSM_ALGO_RunSl3dDepth_doubleIR(tsmTRP_Sl3dData_t* data)
{
	void *ipcm = ipcm_get(IPCM_CPU_ID_CK805);
    CHECK_PARAM(ipcm, -EBUSY);
	
    tsmTRP_Sl3dData_t* p_sl3d = (tsmTRP_Sl3dData_t*)ipcm_get_mem();
    CHECK_PARAM(p_sl3d, -1);
	
    memcpy(p_sl3d, data, sizeof(tsmTRP_Sl3dData_t));
    int* rev;
    int  ret = 0;
    ret = ipcm_sync_send(ipcm, IPC_AIE_PROC_RUN_DOUBLE_IR, (void*)p_sl3d, &rev);
    if (ret != 0) {    
        return ret;
    }

    return 0;
}

int TSM_ALGO_RunSl3dDepth_SingleEye(tsmTRP_Sl3dData_t* data)
{
	void *ipcm = ipcm_get(IPCM_CPU_ID_CK805);
    CHECK_PARAM(ipcm, -EBUSY);
    tsmTRP_Sl3dData_t* p_sl3d = (tsmTRP_Sl3dData_t*)ipcm_get_mem();
    CHECK_PARAM(p_sl3d, -1);
    memcpy(p_sl3d, data, sizeof(tsmTRP_Sl3dData_t));
    int* rev;
    int  ret = 0;
    ret = ipcm_sync_send(ipcm, IPC_AIE_PROC_RUN_SINGLE, (void*)p_sl3d, &rev);
    if (ret != 0) {    
        return ret;
    }
    //data->disp  = ((tsmTRP_Sl3dData_t*)rev)->disp;
    //data->depth = ((tsmTRP_Sl3dData_t*)rev)->depth;
    return 0;
}

int TSM_ALGO_RunSl3dDisp_SingleEye(tsmTRP_Sl3dData_t* data)
{
	void *ipcm = ipcm_get(IPCM_CPU_ID_CK805);
    CHECK_PARAM(ipcm, -EBUSY);
    tsmTRP_Sl3dData_t* p_sl3d = (tsmTRP_Sl3dData_t*)ipcm_get_mem();
    CHECK_PARAM(p_sl3d, -1);
    memcpy(p_sl3d, data, sizeof(tsmTRP_Sl3dData_t));
    int* rev;
    int  ret = 0;
    ret = ipcm_sync_send(ipcm, IPC_AIE_PROC_RUN_SINGLE_DISP, (void*)p_sl3d, &rev);
    if (ret != 0) {    
        return ret;
    }
    data->disp  = ((tsmTRP_Sl3dData_t*)rev)->disp;
    data->depth = ((tsmTRP_Sl3dData_t*)rev)->depth;
    return 0;
}


int TSM_ALGO_RunSl3dDepth_SingleEye_2base(tsmTRP_Sl3dData_Base2_t *req, tsmTRP_Sl3dData_t *resp)
{
	void *ipcm = ipcm_get(IPCM_CPU_ID_CK805);
	CHECK_PARAM(ipcm, -EBUSY);

    tsmTRP_Sl3dData_Base2_t* p_sl3d2base = (tsmTRP_Sl3dData_Base2_t*)ipcm_get_mem();
    CHECK_PARAM(p_sl3d2base, -1);
    memcpy(p_sl3d2base, req, sizeof(tsmTRP_Sl3dData_Base2_t));
    int* rev;
    int  ret = 0;
    ret = ipcm_sync_send(ipcm, IPC_AIE_PROC_RUN_SINGLE_2BASE_DEPTH, (void*)p_sl3d2base, &rev);
    if (ret != 0) {    
        return ret;
    }
    resp->disp  = ((tsmTRP_Sl3dData_t*)rev)->disp;
    resp->depth = ((tsmTRP_Sl3dData_t*)rev)->depth;
    return 0;
}


int TSM_ALGO_InitSl3dDepthcompenSingleEye(tsmTRP_Sl3dCfg_t* data)
{
	void *ipcm = ipcm_get(IPCM_CPU_ID_CK805);
	CHECK_PARAM(ipcm, -EBUSY);
    tsmTRP_Sl3dCfg_t* p_sl3d = (tsmTRP_Sl3dCfg_t*)ipcm_get_mem();
    CHECK_PARAM(p_sl3d, -1);
    memcpy(p_sl3d, data, sizeof(tsmTRP_Sl3dCfg_t));
    int* rev;
    int  ret = 0;
    ret = ipcm_sync_send(ipcm, IPC_AIE_INIT_DEPTH_COMPEN_SINGLE_EYE, (void*)p_sl3d, &rev);
    if (ret != 0) {    
        return ret;
    }
    return 0;
}

int TSM_ALGO_RunSl3dDepthcompenSingleEye(tsmTRP_Sl3dData_t* data)
{
	void *ipcm = ipcm_get(IPCM_CPU_ID_CK805);
	CHECK_PARAM(ipcm, -EBUSY);
    tsmTRP_Sl3dData_t* p_sl3d = (tsmTRP_Sl3dData_t*)ipcm_get_mem();
    CHECK_PARAM(p_sl3d, -1);
    memcpy(p_sl3d, data, sizeof(tsmTRP_Sl3dData_t));
    int* rev;
    int  ret = 0;
    ret = ipcm_sync_send(ipcm, IPC_AIE_PROC_DEPTH_COMPEN_SINGLE_EYE, (void*)p_sl3d, &rev);
    if (ret != 0) {    
		printf("IPC_AIE_PROC_DEPTH_COMPEN_SINGLE_EYE error\n");
        return ret;
    }
    data->disp  = ((tsmTRP_Sl3dData_t*)rev)->disp;
    data->depth = ((tsmTRP_Sl3dData_t*)rev)->depth;
//	printf("in  @ %p\n", rev);
//	printf("disp @ %p\n", data->disp);
//	printf("depth @ %p\n", data->depth);
    return 0;
}

int TSM_ALGO_RunSl3dDepthStreamInit(void)
{
	void *ipcm = ipcm_get(IPCM_CPU_ID_CK805);
	CHECK_PARAM(ipcm, -EBUSY);
    int* p_sl3d = (int*)ipcm_get_mem();
    int* rev;
    int  ret = 0;
    ret = ipcm_sync_send(ipcm, IPC_AIE_SL3D_STREAM_INIT, (void*)p_sl3d, &rev);
    if (ret != 0) {    
		printf("IPC_AIE_PROC_DEPTH_COMPEN_SINGLE_EYE error\n");
        return ret;
    }
    return 0;
}

int TSM_ALGO_RunSl3dDepthStreamIn(tsmTRP_Sl3dData_t* data)
{
	void *ipcm = ipcm_get(IPCM_CPU_ID_CK805);
	CHECK_PARAM(ipcm, -EBUSY);
    tsmTRP_Sl3dData_t* p_sl3d = (tsmTRP_Sl3dData_t*)ipcm_get_mem();
    CHECK_PARAM(p_sl3d, -1);
    memcpy(p_sl3d, data, sizeof(tsmTRP_Sl3dData_t));
    int* rev;
    int  ret = 0;
    ret = ipcm_sync_send(ipcm, IPC_AIE_SL3D_STREAM_IN, (void*)p_sl3d, &rev);
    if (ret != 0) {    
		printf("IPC_AIE_PROC_DEPTH_COMPEN_SINGLE_EYE error\n");
        return ret;
    }
    return 0;
}

int TSM_ALGO_RunSl3dDepthStreamOut(tsmTRP_Sl3dRet_t* result)
{ 
    void *ipcm = ipcm_get(IPCM_CPU_ID_CK805);
	CHECK_PARAM(ipcm, -EBUSY);
    CHECK_PARAM(result, -1);
    int* p_sl3d = (int*)ipcm_get_mem();
    int* rev;
    int  ret = 0;
    ret = ipcm_sync_send(ipcm, IPC_AIE_SL3D_STREAM_OUT, (void*)p_sl3d, &rev);
    if (ret != 0) {    
		printf("IPC_AIE_PROC_DEPTH_COMPEN_SINGLE_EYE error\n");
        return ret;
    }
	result->ret = ((tsmTRP_Sl3dRet_t*)rev)->ret;
    result->depth = ((tsmTRP_Sl3dRet_t*)rev)->depth;
	//printf("rev=%p, depth = %p\n", rev, result->depth);
    return 0;
}


int TSM_TOF_GetIrDepth(tsmTofImg_t* data)
{
    CHECK_PARAM(data, -1);
	void *ipcm = ipcm_get(IPCM_CPU_ID_CK805);
	CHECK_PARAM(ipcm, -EBUSY);
    int* rev;
    int  ret = 0;
    tsmTofImg_t* ptr = (tsmTofImg_t*)data;
 
    ret = ipcm_sync_send(ipcm, IPC_TOF_GET_IR_DEPTH, (void*)ptr, &rev);
    if (ret != 0) {    
        return -1;
    }
    int result = *(int*)rev;
    return result;
}

int TSM_ALGO_HumanPoseInit(TsmHandle handle, int h, int w)
{
    void *ipcm = ipcm_get(IPCM_CPU_ID_CK805);
	CHECK_PARAM(ipcm, -EBUSY);
    tsmHumanPose* p_init_param = (tsmHumanPose *)ipcm_get_mem();
    CHECK_PARAM(p_init_param, -ENOMEM);
    p_init_param->h            = h;
    p_init_param->w            = w;
    
    int* rev ;
    int  ret = 0;
    ret = ipcm_sync_send(ipcm, IPC_HUMANPOSE_INIT, (void*)p_init_param, &rev);
    if (ret != 0) { 
        return ret;
    }
    
    return (int)*rev;
}

TsmPoseResult *TSM_ALGO_HumanPoseDetect(TsmHandle handle, uint32_t *img_0rgb,
                              tsmDeviceParam *param)
{
	void *ipcm = ipcm_get(IPCM_CPU_ID_CK805);
	CHECK_PARAM(ipcm, NULL);
	
    tsmHmanPoseInput * p_proc_run = (tsmHmanPoseInput *)ipcm_get_mem();
    CHECK_PARAM(p_proc_run, NULL);
   
    /* TODO: check user`s param ? */
    p_proc_run->vis   = img_0rgb;
    memcpy(&(p_proc_run->param), param, sizeof(tsmDeviceParam));
    int* rev;
    int  ret = 0;
    ret = ipcm_sync_send(ipcm, IPC_HUMANPOSE_DETECT, (void*)p_proc_run, &rev);
    if (ret != 0) {    
        return NULL;
    }
    TsmPoseResult* result = (TsmPoseResult*)rev;
    return result;
}

int TSM_ALGO_ImageBina(grey_img_t *in , grey_img_t* out)
{
	void *ipcm = ipcm_get(IPCM_CPU_ID_CK805);
	CHECK_PARAM(ipcm, -EBUSY);
    tsmTRP_Bina_t* p_proc_run = (tsmTRP_Bina_t *)ipcm_get_mem();
    CHECK_PARAM(p_proc_run, -1);
    
    /* TODO: check user`s param ? */
    p_proc_run->in = in;
    p_proc_run->out = out;

    int* rev;
    int  ret = 0;
    ret = ipcm_sync_send(ipcm, IPC_IMAGE_BINA, (void*)p_proc_run, &rev);
    if (ret != 0) {    
        return -1;
    }
    return (int)rev;
}

char *TSM_ALGO_GetVersion(TsmHandle handle)
{
	void *ipcm = ipcm_get(IPCM_CPU_ID_CK805);
	CHECK_PARAM(ipcm, NULL);
    int* rev;
    int  ret = 0;
	uint8_t *ipcm_mem = ipcm_get_mem();
    ret = ipcm_sync_send(ipcm, IPCM_GET_VERSION, (void*)ipcm_mem, &rev);
    if (ret != 0) {    
        return NULL;
    }
    char* result = (char*)rev;
    return result;
}

char *TSM_ALGO_GetModelVersion(TsmHandle handle)
{
    void *ipcm = ipcm_get(IPCM_CPU_ID_CK805);
	CHECK_PARAM(ipcm, NULL);
    int* rev;
    int  ret = 0;
	uint8_t *ipcm_mem = ipcm_get_mem();
    ret = ipcm_sync_send(ipcm, IPCM_GET_MODEL_VERSION, (void*)ipcm_mem, &rev);
    if (ret != 0) {    
        return NULL;
    }
    char* result = (char*)rev;
    return result;
}

int TSM_ALGO_RunAmrRotate90(tsmImg_t* src, tsmImg_t* dst, uint8_t rotate)
{
	void *ipcm = ipcm_get(IPCM_CPU_ID_CK805);
	CHECK_PARAM(ipcm, -EBUSY);
    static int affine_init = 0;
    if (affine_init == 0) {
        affine_init++;
    }
    tsmResizeData_t* p_amr = (tsmResizeData_t*)ipcm_get_mem();
    CHECK_PARAM(src, -1);
    CHECK_PARAM(dst, -1);
    memcpy(&(p_amr->src), src, sizeof(tsmImg_t));
    memcpy(&(p_amr->dst), dst, sizeof(tsmImg_t));
    *(uint8_t*)(p_amr + 1) = rotate;
    int* rev;
    int  ret = 0;
    ret = ipcm_sync_send(ipcm, IPC_AIE_PROC_ROTATE90, (void*)p_amr, &rev);
    if (ret != 0) {    
        return -1;
    }
    int result = *(int*)rev;
    return result;
}

void tsm_algo_set_805_log_level(uint8_t level)
{
	void *ipcm = ipcm_get(IPCM_CPU_ID_CK805);
	CHECK_PARAM(ipcm,);
    int* rev;
    int  ret = 0;
	uint8_t *ipcm_mem = ipcm_get_mem();
    *ipcm_mem = level;
    ret = ipcm_sync_send(ipcm, IPCM_SET_LOG_LEVEL, (void*)ipcm_mem, &rev);
    if (ret != 0) {    
        return;
    }
    return;
}
